#include "Defs.h"
#include "Timer.h"


Timer_T::Timer_T()
{
	FILETIME ft0 = { 0, 0 };
	FILETIME ft1 = { 0, 0 };
	LARGE_INTEGER li;

	//
	// Spin waiting for a change in system time. Get the matching
	// performance counter value for that time.
	//
	GetSystemTimeAsFileTime(&ft0);
	do
	{
		GetSystemTimeAsFileTime(&ft1);
		QueryPerformanceCounter(&li);
	}
	while( (ft0.dwHighDateTime == ft1.dwHighDateTime) && (ft0.dwLowDateTime == ft1.dwLowDateTime) );

	_fileTime = ft1;
	_counter = li;
	QueryPerformanceFrequency(&_frequency);
}

void Timer_T::GetCurrent(FILETIME & currentTime)
{
	LARGE_INTEGER li;
	LARGE_INTEGER ticksElapsed;
	ULARGE_INTEGER filetimeTicks, filetime_ref_as_ul;

	QueryPerformanceCounter(&li);

	//
	// Calculate performance counter ticks elapsed
	//
	ticksElapsed.QuadPart = li.QuadPart - _counter.QuadPart;

	//
	// Translate to 100-nanoseconds intervals (FILETIME resolution)
	// and add to reference FILETIME to get current FILETIME.
	//
	filetimeTicks.QuadPart = (ULONGLONG)((((double)ticksElapsed.QuadPart/ (double)_frequency.QuadPart) * 10000000.0) + 0.5);
	filetime_ref_as_ul.HighPart = _fileTime.dwHighDateTime;
	filetime_ref_as_ul.LowPart = _fileTime.dwLowDateTime;
	filetime_ref_as_ul.QuadPart += filetimeTicks.QuadPart;

	//
	// Copy to result
	//
	currentTime.dwHighDateTime = filetime_ref_as_ul.HighPart;
	currentTime.dwLowDateTime = filetime_ref_as_ul.LowPart;
}

void Timer_T::GetCurrent(SYSTEMTIME & currentTime)
{
	FILETIME ft;
	GetCurrent(ft);
	FileTimeToSystemTime(&ft, &currentTime);
}

unsigned int Timer_T::GetElapsed(FILETIME & oldTime)
{
	FILETIME ftNow;
	ULARGE_INTEGER ulOld, ulNow;
	GetCurrent(ftNow);
	RtlMoveMemory(&ulOld, &oldTime, sizeof(oldTime));
	RtlMoveMemory(&ulNow, &ftNow, sizeof(ftNow));

	return (unsigned int)(ulNow.QuadPart - ulOld.QuadPart) / 10000;
}